from Quality import *
from Utility import *
from BeautifulSoup import BeautifulSoup
from BeautifulSoup import BeautifulStoneSoup
import sys, time, re, os, random
from nltk import pos_tag, word_tokenize
from nltk.stem.porter import PorterStemmer
from nltk.stem.wordnet import WordNetLemmatizer
import datetime

class Exp():
    def __init__(self,id=None,company=None,position=None,period=None,expDesc=None):
        self.id=id
        self.company=company
        self.position=position
        self.period=period
        self.expDesc=expDesc
        self.duration=self.getDuration()
        self.leadership=self.getLeadership()
        self.workAreas=self.getWorkArea()
        
    def getDuration(self):
        def calDuration(p):
            """return duration as # of month"""
            tmp_lst=p.split('-')
            if len(tmp_lst)<>2: return 0
            
            t={'y1':0,'m1':0,'y2':0,'m2':0}
            m={'jan':1,'feb':2,'mar':3,'apr':4,'may':5,'jun':6,'jul':7,'aug':8,'sep':9,'oct':10,'nov':11,'dec':12}
            a=tmp_lst[0].lower().strip()
            b=tmp_lst[1].lower().strip()
            #precess the lower bound
            if isNumeric(a):
                if len(a)==4:
                    t['y1']=int(a)
                else:
                    t['y1']=int(a[len(a)-4:])
                    t['m1']=int(a[:len(a)-4])
            else:
                if a in ['present','now']:
                    t['y1']=datetime.datetime.now().year
                else:
                    delimiter=''
                    if a.find('/')<>-1:
                        delimiter='/'
                    elif a.find(',')<>-1:
                        delimiter=','
                    elif a.find(' ')<>-1:
                        delimiter=' '
                    #print a.split(delimiter)
                    t['m1'],t['y1']=a.split(delimiter)
                    t['y1']=int(t['y1'].strip())
                    t['m1']=t['m1'].strip()
                    if isNumeric(t['m1']):
                        t['m1']=int(t['m1'])
                    else:
                        t['m1']=m[t['m1'][:3]]
                        
            #process the upper bound
            if isNumeric(b):
                if len(b)==4:
                    t['y2']=int(b)
                else:
                    t['y2']=int(a[len(b)-4:])
                    t['m2']=int(a[:len(b)-4])
            else:
                if b in ['present','now','to date']:
                    t['y2']=datetime.datetime.now().year
                else:
                    delimiter=''
                    if b.find('/')<>-1:
                        delimiter='/'
                    elif b.find(',')<>-1:
                        delimiter=','
                    elif b.find(' ')<>-1:
                        delimiter=' '
                    t['m2'],t['y2']=b.split(delimiter)
                    t['y2']=int(t['y2'].strip())
                    t['m2']=t['m2'].strip()
                    if isNumeric(t['m2']):
                        #print t['m2']
                        t['m2']=int(t['m2'])
                    else:
                        #print t['m2'][:3]
                        t['m2']=m[t['m2'][:3]]
            return (t['m2']+12*t['y2'])-(t['m1']+12*t['y1'])
            
        period=self.period
        duration=0
        if period:
            #skipe the case of multiple durations; may be implemented later
            if period.find('-')<>-1:
                if period.find(',')<>-1:
                    for p in period.split(','):
                        duration+=calDuration(p)
                else:
                    duration+=calDuration(period)
        return duration
        
            
    def getLeadership(self):
        leadership=Leadership(id=self.id,position=self.position,duration=self.duration,company=self.company)
        return leadership
    
    def getWorkArea(self):
        workAreas=[]
        p=self.expDesc
        v=('VBN','VBD','VB','VBP','VBZ')
        n=('NN','NNS','NNP','NNPS')
        for s in p.split('.'):
            s=s.strip()
            if not s:
                continue
            s=s[0].lower()+s[1:]
            if s:
                #print len(s)
                token_pos_pairs=zip(*pos_tag(word_tokenize('I '+s)))
                tmp=[]
                for i in range(0,len(token_pos_pairs[1])):
                    if token_pos_pairs[1][i] in n:
                        tmp.append(token_pos_pairs[0][i].lower())
                    else:
                        if len(tmp)>0:
                            workAreas.append(tmp)
                            tmp=[]
        #print workAreas
        for i in range(0,len(workAreas)):
            workAreas[i]=' '.join(workAreas[i])
        #print workAreas
        #exit()
        return workAreas
        
#--------------------------------Resume Class--------------------------------
class Resume(object):
    def __init__(self, id=None, file=None, keyWords=None):
        fr=open(file,'r')
        #beautiful soup variables
        html=fr.read()
        self.soup=BeautifulSoup(html)
        self.name = self.soup.html.head.title.string
        self.id=id
        self.file = file
        self.keyWordsCount={}
        for keyWord in keyWords:
            self.keyWordsCount[keyWord]=0
        print "Parsing experience...."
        #time.sleep(2)
        self.exps=self.getExps(keyWords)
        print "Parsing education...."
        #time.sleep(1)
        self.edus=self.getEdus()
        print "Parsing skills...."
        #time.sleep(1)
        self.skills=self.getSkills()
        print "Parsing certifications...."
        #time.sleep(1)
        self.generateClipsCode()
    
        
    
    #get raw info about all working experiences
    def getExps(self,keyWords):
        body=self.soup.find("body")
        expDivs=body.find('div',attrs={'id' : re.compile("experience")}).findAll('div',attrs={'id' : re.compile("company")})
        numOfCompany=len(expDivs)
        #print numOfCompany
        #the exps lst to be returned
        exps=[]
        totalTime=0.0
        avgTime=0.0
        for expDiv in expDivs:
            try:
                company=expDiv['title'].lower().strip()
            except NameError:
                company=''
            try:
                positions=expDiv.findAll('div',attrs={'id': re.compile("position")})
            except NameError:
                positions=[]
            try:
                durations=expDiv.findAll('div',attrs={'id': re.compile("time")})
            except NameError:
                durations=[]
            try:
                expDescs=expDiv.findAll('div',attrs={'id': re.compile("experience")})
            except NameError:
                expDescs=[]
            #print positions
            for i in range(0,len(positions)):
                for keyWord in keyWords:
                    #print expDescs[i],keyWord,expDescs[i].string.lower().find(keyWord.lower())
                    positionStr=positions[i].string.lower().strip()
                    expStr=expDescs[i].string.strip()
                    if expStr.lower().find(keyWord.lower())<>-1:
                        try:
                            self.keyWordsCount[keyWord]+=1
                        except KeyError:
                            self.keyWordsCount[keyWord]=1
                    if positionStr.lower().find(keyWord.lower())<>-1:
                        try:
                            self.keyWordsCount[keyWord]+=1
                        except KeyError:
                            self.keyWordsCount[keyWord]=1
                try:
                    durationStr=durations[i].string.lower().strip()
                except Exception:
                    durationStr=''
                #print durationStr
                exp=Exp(self.id,company,positionStr,durationStr,expStr)
                totalTime+=exp.duration
                exps.append(exp)
        if numOfCompany<>0:
            avgTime=totalTime/numOfCompany
            
        self.loyalty=loyalty(self.id,numOfCompany,avgTime)
        return exps
    
    def getEdus(self):
        body=self.soup.find("body")
        eduDivs=body.find('div',attrs={'id' : re.compile("education")}).findAll('div',attrs={'id' : re.compile("edu")})
        edus=[]
        degrees=[["high"],
                 ["associate","A.S.","A.A.","A.A.S."],
                 ["b.a.","bs","ba","b.s.","b. s. ","b. s.","bsci","b.sci","bsc","Bachelor of Science","Bachelor of art","Bachelor"],
                 ["M.A.","MS","MA","M.Sc.","A.M.","S.M.","AM","SM","m.s.","Master of Science","Master of Art","Master"],
                 ["Ph.D.","DPhil","D.Phil.","PHD","PH.D","PHD."]]
        for eduDiv in eduDivs:
            try:
                degree=eduDiv.find('div',attrs={'id' : re.compile("degree")}).string.lower().strip()
            except Exception:
                degree='Unknown'
            #print degree
            degreeScore=0
            flg=False
            for i in range(0,len(degrees)):
                if flg: break
                #print degrees[i]
                for a in degrees[i]:
                    #print degree.find(a.lower())
                    if degree.find(a.lower())<>-1:

                        degreeScore=(i+1)
                        #print "degreeScore",a,degreeScore
                        flg=True
                        break
            try:
                major=eduDiv.find('div',attrs={'id' : re.compile("major")}).string.lower().strip()
            except Exception:
                major='Unknown'
            try:
                gradTime=eduDiv.find('div',attrs={'id' : re.compile("deg_time")}).string.lower().strip()
            except Exception:
                gradTime='Unknown'
            try:
                school=eduDiv.find('div',attrs={'id' : re.compile("university")}).string.lower().strip()
            except Exception:
                school='Unknown'
            try:
                schAdd=eduDiv.find('div',attrs={'id' : re.compile("uni_address")}).string.lower().strip()
            except Exception:
                schAdd='Unknown'
            #self,id=None,degree=None,major=None,gradTime=None,school=None
            edu=Education(self.id,degree,degreeScore,major,gradTime,school)
            edus.append(edu)
        return edus

    def getSkills(self):
        body=self.soup.find("body")
        skillDiv=body.find('div',attrs={'id' : re.compile("skill")})
        setDivs=skillDiv.findAll('div',attrs={'id' : re.compile("set")})
        skillLst=[]
        for setDiv in setDivs:
            s='\t'.join(setDiv.findAll(text=True)).strip()
            while(s.find(':')<>-1):
                s=s.replace(':','\t')
            while(s.find(',')<>-1):
                s=s.replace(',','\t')
            while(s.find('\n')<>-1):
                s=s.replace('\n','\t')
            while(s.find(';')<>-1):
                s=s.replace(';','\t')
            while(s.find('\t\t')<>-1):
                s=s.replace('\t\t','\t')
            for a in s.split('\t'):
                b=a.lower().strip()
                if b not in skillLst:
                    skillLst.append(b)
        return skillLst
    def getHighestDegree(self):
        a=0
        for edu in self.edus:
            if edu.degreeScore>a:
                a=edu.degreeScore
        #print a
        return a
    def generateClipsCode(self):
        print "Output file:"+"clps/"+self.id+"_"+self.name+".clp"
        fw=open("clps/"+self.id+"_"+self.name+".clp","w")
        s="(deffacts Person%s\n\t(Person (ID %s) (Name \"%s\") (Path \"%s\") (highestDegree %d))\n\
)\n" % (self.id,self.id,self.name,self.file,self.getHighestDegree())
       
        s+="(deffacts MonthsExperience%s\n\t(MonthsExperience (ID %s) (months %.2f))\n\
)\n" % (self.id,self.id,self.loyalty.numOfCompany*self.loyalty.avgTime)
        s+="\n(deffacts LeadershipExp%s\n" % (self.id)
        for exp in self.exps:
            leadership=exp.leadership
            s+="\t(LeadershipExp (ID %s) (position \"%s\") (level \"%s\") (company \"%s\") (duration %.2f))\n" % (self.id,leadership.position,leadership.level,leadership.company,leadership.duration)
        s+=")\n" 
            
        s+="\n(deffacts WorkAreaExp%s\n" % (self.id)
        for exp in self.exps:
            for workArea in exp.workAreas:
                s+="\t(WorkAreaExp (ID %s) (name \"%s\") (duration %.2f))\n" % (self.id,workArea,exp.duration)
        s+=")\n" 
        
        s+="\n(deffacts Skill%s\n" % (self.id)
        for skill in self.skills:
            s+="\t(Skills (ID %s) (skill \"%s\"))\n" % (self.id,skill)
        s+=")\n" 
        
        s+="\n(deffacts Education%s\n" % (self.id)
        for edu in self.edus:
            s+="\t(Education (ID %s) (school \"%s\") (major \"%s\") (degree \"%s\") (GPA %.1f) (degreelevel %d))\n" \
            % (self.id,edu.school,edu.major,edu.degree,random.randrange(30,40,1)*0.1,edu.degreeScore)
        s+=")\n"
        
        s+="\n(deffacts KeyWordOccurance%s\n" % (self.id)
        for keyWord,count in self.keyWordsCount.items():
            s+="\t(KeyWordOccurance (ID %s) (Phrase \"%s\") (Count %d))\n" % (self.id,keyWord,count)
        s+=")\n"
        #print s
        fw.write(s)
        #print body
